package com.jf3q.gateway.security.filter;

import com.google.gson.Gson;
import com.jf3q.common.dto.ResultDto;
import com.jf3q.gateway.security.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

@Component
@Slf4j
public class JwtWebFilter implements GlobalFilter, Ordered {
    @Autowired
    JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Override
    public int getOrder() {
        return -100;
    }
    /**
     * 过滤器
     *
     * @param exchange  链路处理
     * @param chain 拦截或放行
     * @return 鉴权结果
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpResponse resp = exchange.getResponse();
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();
        List<String> tokenList = request.getHeaders().get(tokenHeader);

        if (CollectionUtils.isEmpty(tokenList)) {
            log.info("JwtWebFilter.filter->请求未携带token");
            return authErro(resp,"登录过期，请重新登录");
        }
        String authToken = tokenList.get(0);

        if (null != authToken && authToken.startsWith(tokenHead)) {

            String token = authToken.substring(tokenHead.length());

            //验证token是否有效，重新设置用户对象
            if (jwtTokenUtil.validateToken(token)) {
                return chain.filter(exchange);
            }else{
                return authErro(resp,"token不合法");
            }


        }else{
            return authErro(resp,"token不合法");
        }


    }

    /**
     * 认证错误输出
     *
     * @param resp 响应对象
     * @param mess 错误信息
     * @return 错误结果
     */
    private Mono<Void> authErro(ServerHttpResponse resp, String mess) {
        Gson gson=new Gson();
        resp.setStatusCode(HttpStatus.FORBIDDEN);
        resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

        ResultDto resultDto = ResultDto.error(mess);
        String returnStr = "";
        try {
            returnStr = gson.toJson(resultDto);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        DataBuffer buffer = resp.bufferFactory().wrap(returnStr.getBytes(StandardCharsets.UTF_8));
        return resp.writeWith(Flux.just(buffer));
    }

}
